const os = require('os')
const path = require('path')
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")

// cpu核数
const threads = os.cpus().length 

// 获取处理样式的loaders
const getStyleLoaders = (preProcessor) => {
  // 从右到左，从下到上
  return [
    // 将 JS 字符串生成为 style 节点
    MiniCssExtractPlugin.loader, 
    // 将 CSS 转化成 CommonJS 模块
    'css-loader',
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor
  ].filter(Boolean) // 过滤preProcessor: undefined的情况
}

module.exports = {
  // 入口
  entry: './src/main.js',
  // 输出
  output: {
    // 文件输出路径
    path: path.resolve(__dirname, '../dist'),
    // 入口文件名
    filename: 'static/js/[name].[contenthash:8].js',
    // 给打包输出的其他文件命名
    chunkFilename: 'static/js/[name].chunk.[contenthash:8].js',
    // 图片、字体等资源命名方式（注意用hash）
    assetModuleFilename: 'static/media/[hash:8][ext][query]',
    // 自动清空上次打包的内容
    // 原理：在打包前，将path整个目录内容清空
    // webpack5
    clean: true
  },
  // 加载器
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.css$/i,
            use: getStyleLoaders(), // 从右到左，从下到上
          },
          {
            test: /\.less$/i,
            use: getStyleLoaders('less-loader')
          },
          {
            test: /\.s[ac]ss$/i,
            use: getStyleLoaders('sass-loader')
            // use: [
            //   // 将 JS 字符串生成为 style 节点
            //   MiniCssExtractPlugin.loader,
            //   // 将 CSS 转化成 CommonJS 模块
            //   'css-loader',
            //   // 将 Sass 编译成 CSS
            //   'sass-loader',
            // ],
          },
          {
            test: /\.(png|jpe?g|gif|webp|svg)$/,
            type: 'asset',
            parser: {
              dataUrlCondition: {
                // 小于10kb 装换为base64
                // 优点： 减少请求数量 缺点：体积大
                maxSize: 10 * 1024
              }
            },
            generator: {
              // 输出图片名称
              // [hash:8] hash值取前8位
              filename: 'static/images/[hash:8][ext][query]'
            }
          },
          {
            test: /\.(ttf|woff2?|mp4)$/,
            type: 'asset/resource',
            // generator: {
            //   // 输出图片名称
            //   // [hash:8] hash值取前8位
            //   filename: 'static/media/[hash:8][ext][query]'
            // }
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            use: [
              {
                loader: 'thread-loader', // 开启多进程
                options: {
                  workers: threads // 数量
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true, // 开启babel编译缓存
                  cacheCompression: false, // 缓存文件不要压缩, 提升打包速度
                  plugins: ["@babel/plugin-transform-runtime"] // 减少代码体积
                }
              }
            ]
          }
        ]
      }
    ]
  },
  // optimization: {
  //   minimizer: [
  //     // 在 webpack@5 中，你可以使用 `...` 语法来扩展现有的 minimizer（即 `terser-webpack-plugin`），将下一行取消注释
  //     // `...`,
  //     new CssMinimizerPlugin(),
  //   ],
  // },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, '../src'),
      cache: true, // 开启缓存
      // 缓存目录
      cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'),
      threads // 开启多进程
    }),
    new HtmlWebpackPlugin({
      // 模板: 以public/index.html 文件创建新的html文件
      // 新的html文件特点： 1.结构和原来一致 2.自动引入打包的资源
      template: path.resolve(__dirname, '../public/index.html')
    }),
    new MiniCssExtractPlugin({
      filename: 'static/css/[name].[contenthash:8].css',
      chunkFilename: 'static/css/[name].chunk.[contenthash:8].css',
    }),
    // 压缩的操作
    // 压缩css
    new CssMinimizerPlugin(),
    new TerserPlugin({
      parallel: threads // 开启多进程和设置进程数量
    })
  ],
  optimization: {
    // 代码分割配置
    splitChunks: {
      chunks: "all", // 对所有模块都进行分割
    },
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}.js`
    }
  },
  // 模式
  mode: 'production',
  devtool: 'source-map'
}